package com.leesche.netdoll.communication;

import java.util.Map.Entry;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import com.leesche.framework.core.lang.CollectionUtil;
import com.leesche.framework.core.lang.StringUtil;
import com.leesche.framework.platform.redis.HashCommand;
import com.leesche.framework.platform.redis.KeyCommand;
import com.leesche.framework.platform.redis.RedisManager;
import com.leesche.framework.platform.redis.ScanDataSet;
import com.leesche.netdoll.communication.Settings.RedisModule;
import com.leesche.netdoll.communication.Settings.ServerConfig;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
@Component
public class NetDollServer implements ApplicationRunner {

	private static final Logger logger = LogManager.getLogger(NetDollServer.class);

	@Override
	public void run(ApplicationArguments var1) {
		logger.info("Server is starting up...");
		Settings.loadSettings();

		reset();

		EventLoopGroup bossGroup = new NioEventLoopGroup(ServerConfig.BOSS_SIZE);
		EventLoopGroup workerGroup = new NioEventLoopGroup(ServerConfig.WORKER_SIZE);

		try {
			ServerBootstrap bootStrap = new ServerBootstrap();

			bootStrap.group(bossGroup, workerGroup)//
					.channel(NioServerSocketChannel.class)//
					.handler(new LoggingHandler(LogLevel.TRACE)) //
					.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(8 * 1024, 32 * 1024))//
					.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)//
					.childOption(ChannelOption.SO_KEEPALIVE, true)//
					.childOption(ChannelOption.TCP_NODELAY, true)//
					.childHandler(new ServerInitializer());

			ChannelFuture f = bootStrap.bind(ServerConfig.PORT).sync();

			if (f.isSuccess()) {
				OutboundDataSender.sender().start();
				logger.info("Server [{}] started: listening at [{}]", ServerConfig.IP, ServerConfig.PORT);
			}

			f.channel().closeFuture().sync();

		} catch (Exception e) {
			logger.catching(e);
			Thread.currentThread().interrupt();
		} finally {
			workerGroup.shutdownGracefully();
			bossGroup.shutdownGracefully();
		}
	}
/*
	public static void main(String[] args) {
		try {
			Settings.loadSettings();

			reset();

			NetDollServer server = new NetDollServer();
			server.start();

		} catch (Exception e) {
			logger.catching(e);
			System.exit(1);
		}
	}*/

	public static void reset() {
		logger.info("reset device status...");

		KeyCommand redis = RedisManager.custom().getKeyCommand(RedisModule.TERMINAL);
		// redis.del(RedisModule.KEY_DS);
		redis.del(RedisModule.KEY_OUTBOUND);
		// redis.del(RedisModule.KEY_DEVICE_IDLE);
		resetGameStatus();

		logger.info("reset device status...OK");
	}

	private static void resetGameStatus() {
		HashCommand redis = RedisManager.custom().getHashCommand(RedisModule.TERMINAL);

		boolean scanFinish = false;
		String cursor = "0";

		while (!scanFinish) {
			ScanDataSet rs = redis.hScan(RedisModule.KEY_GS, cursor, 500);

			if (rs != null && rs.getResult() != null) {
				cursor = rs.getCursor();
				if ("0".equals(cursor)) {
					scanFinish = true;
				}
				if (CollectionUtil.isNotEmpty(rs.getResult())) {
					for (Entry<String, String> entry : rs.getResult()) {

						String value = entry.getValue();
						if (StringUtil.isNotBlank(value)) {

						}
					}
				}
			} else {
				scanFinish = true;
			}
		}
	}
}
